"""
Copyright 2012 Wieser Dietmar, Margit Mutschlechner.

This file is part of Multimedia Social Networking Platform.

Multimedia Social Networking Platform is free software: 
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Multimedia Social Networking Platform is distributed
in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Multimedia Social Networking Platform.  
If not, see <http://www.gnu.org/licenses/>.

"""

from msnp.logger import Logger
import traceback
from msnp.service import network
from threading import Thread
import sys
from msnp.service.network.listening.Listener import ListeningThread
from msnp.service.network import networktimer
from msnp.service.synch import timer
from msnp import gui

class Finish(Thread):
    """Thread which is executed during a leave request.

    Attributes:
        __quit: a boolean determining whether the user requested a logout or an exit of the application
        __running: a boolean determining whether the Finish instance is already executing the run method
    """
    
    def __init__(self, quit):
        """the init method"""
        
        Thread.__init__(self)
        self.__quit = quit
        self.__running = False


    def run(self):
        """The run method executes the leave request"""
        
        self.__running = True
        try:
            if self.__quit:
                self.__executeQuit()
            else:
                self.__executeLogout()
        except:
            Logger.info(traceback.format_exc())
        self.__running = False
        resetLeaveRequest()
            
            
    def __executeQuit(self):
        """This method executes an exit request. All network threads are stopped and the application terminates."""
        
        Logger.info("LeaveRequest: Now I try to leave the network.")
        if network.NetworkController.getMySelf().isAuthenticated():
            if network.NetworkController.leaveNetwork():
                Logger.info("Leaved successful")
            else:
                Logger.info("Something went wrong while leaving the network")
                
            Logger.info("Finish -> Try to stop all listeners and timers")
        else:
            Logger.info("Not authenticated yet -> no leave request sent.")
        try:
            sys.exit()
        except:
            ListeningThread.stopListening()
            networktimer.ResendTimer.stopResendTimer()
            networktimer.KeepAliveTimer.stopKeepAliveTimer()
            networktimer.LowLevelPeerCrashTimer.stopLowLevelPeerCrashTimer()
            timer.RescanTimer.stopTimer()
            timer.SynchChangesTimer.stopTimer()
            Logger.info("All listener and timer stopped, now stop GUI...")
            gui.GUIController.stopGUI()
            Logger.info("GUI stopped")
    
    
    def __executeLogout(self):
        """This method executes a logout request. All network threads are stopped and the login screen will be displayed."""
        
        Logger.info("LeaveRequest: Now I try to leave the network.")
        if network.NetworkController.leaveNetwork():
            Logger.info("Leaved successful")
        else:
            Logger.info("Something went wrong while leaving the network")
            
        Logger.info("Finish -> Try to stop all listeners and timers")
        ListeningThread.stopListening()
        networktimer.ResendTimer.stopResendTimer()
        networktimer.KeepAliveTimer.stopKeepAliveTimer()
        networktimer.LowLevelPeerCrashTimer.stopLowLevelPeerCrashTimer()
        timer.RescanTimer.stopTimer()
        timer.SynchChangesTimer.stopTimer()
        Logger.info("All listener and timer stopped, now start login screen...")
        gui.MySignal.emitLogoutSignal()


    def isRunning(self):
        return self.__running

#the Finish instance (Thread)
__finishObject = None
#if this integer is 0 the thread may be started
__finishPossible = 0

def resetLeaveRequest():
    """This function sets the Finish instance to None and the counter to zero."""
    
    global __finishObject
    global __finishPossible
    __finishObject = None
    __finishPossible = 0


def block():
    """This function increments the counter"""
    
    global __finishPossible
    __finishPossible += 1


def release():
    """This function decrements the counter and calls the __notifyFinish function."""
    
    global __finishPossible
    try:
        if __finishPossible > 0:
            __finishPossible -= 1
        __notifyFinish()
    except:
        Logger.info("Exception while releasing leaverequest")


def requestFinish(quit):
    """This function is called if a user wants to leave the network.
    
    Args:
        quit: a boolean determining whether the user requested a logout or an exit of the application
    """
    
    global __finishObject
    __finishObject = Finish(quit)
    __notifyFinish()
    
    
def __notifyFinish():
    """This function starts the Finish thread if the counter is equal zero and the thread is not running yet."""
    
    global __finishObject
    global __finishPossible
    if __finishObject != None and __finishPossible == 0 and __finishObject.isRunning() == False:
        __finishObject.start()
        
